<template>
    <div class="login">
        <a-spin :tip="$t('loadingText')" :spinning="spinning">
            <a-form :model="loginForm" :rules="rules" :label-col="{ span: 6 }" :wrapper-col="{ span: 15 }" @finish="login">
                <dl>
                    <dt>
                        <strong>{{ $t('systemName') }}</strong>
                    </dt>
                    <a-form-item name="username" :label="$t('login.username')">
                        <a-input v-model:value="loginForm.username" :maxlength="50"
                            :placeholder="$t('login.required.username')" />
                    </a-form-item>
                    <a-form-item name="password" :label="$t('login.password')">
                        <a-input-password v-model:value="loginForm.password" :maxlength="12"
                            :placeholder="$t('login.required.password')" />
                    </a-form-item>
                    <a-form-item name="verificationCode" :label="$t('login.verificationCode')">
                        <a-input v-model:value="loginForm.verificationCode" :maxlength="4"
                            :placeholder="$t('login.required.verificationCode')" />
                        <img style="cursor: pointer; position: absolute; top: 0px; right: 1px" :src="verificationCode"
                            @click="getVerificationCode" />
                    </a-form-item>
                    <a-form-item :wrapper-col="{ span: 20, offset: 6 }">
                        <a-dropdown-button>
                            <span class="lang">
                                <ali-icon :type="lang" viewBox="0 0 1024 1024" />
                            </span>
                            {{ showLang() }}
                            <template #overlay>
                                <a-menu @click="switchLang">
                                    <a-menu-item key="zh-cn">
                                        <ali-icon type="travel-zhongguo" viewBox="0 0 1024 1024"
                                            :style="{ fontSize: '15px' }" />中文-简体
                                    </a-menu-item>
                                    <a-menu-item key="en">
                                        <ali-icon type="travel-yingguo" viewBox="0 0 1024 1024"
                                            :style="{ fontSize: '15px' }" />English
                                    </a-menu-item>
                                </a-menu>
                            </template>
                        </a-dropdown-button>
                        <a-button type="primary" html-type="submit" style="margin-left: 20px">{{ $t("login.loginBtn")
                        }}</a-button>
                    </a-form-item>
                </dl>
            </a-form>
        </a-spin>
    </div>
</template>

<script setup lang='ts'>
import i18n from '@/i18n';
import cache from '@/utils/cache';
import { LoginDto } from '@/models/authorize';
import { getVerificationCodeApi, loginApi } from '@/services/account';
import { onMounted, reactive, ref, type FunctionalComponent, type Ref } from 'vue';
import { createFromIconfontCN } from '@ant-design/icons-vue';
import type { IconFontProps } from '@ant-design/icons-vue/lib/components/IconFont';
import router from '@/router';
import type { Rule } from 'ant-design-vue/lib/form';
import { getMd5Suffix } from '@/utils';

const aliIcon: FunctionalComponent<IconFontProps, {}> = createFromIconfontCN({
    scriptUrl: '//at.alicdn.com/t/font_1575409_9o3qqiqchwq.js'
});
const spinning: Ref<boolean> = ref<boolean>(false);
const verificationCode: Ref<string> = ref<string>('');
const lang: Ref<string> = ref<string>('');
const loginForm: LoginDto = reactive<LoginDto>(new LoginDto);
const rules: Record<string, Rule[]> = {
    username: [
        {
            required: true,
            message: i18n.global.t('login.required.username'),
            trigger: 'blur',
        },
    ],
    password: [
        {
            required: true,
            message: i18n.global.t('login.required.password'),
            trigger: 'blur',
        },
    ],
    verificationCode: [
        {
            validator: verificationCode_validator,
            trigger: 'blur',
        },
    ],
}

/**
 * 渲染完成函数
 */
onMounted(() => {
    getVerificationCode();
});

/**
 * 用户校验码验证
 * @param rule 
 * @param value 
 * @param callback 
 */
function verificationCode_validator(
    rule: Rule,
    value: string,
    callback: Function
): Promise<void> {
    if (!value) {
        return Promise.reject(i18n.global.t('login.required.verificationCode'));
    }
    if (!/^[a-zA-Z0-9]{4}$/.test(value)) {
        return Promise.reject(i18n.global.t('login.required.verification'));
    }
    return Promise.resolve();
}

/**
 * 获取验证码
 */
async function getVerificationCode(): Promise<void> {
    const response = await getVerificationCodeApi();
    verificationCode.value = response.base64VerificationCode;
    loginForm.verificationIdentifier = response.verificationIdentifier;
}

/**
 * 显示多语言名称
 */
function showLang(): string {
    switch (cache.getLocale()) {
        case 'zh-cn':
        default:
            lang.value = 'travel-zhongguo';
            return '中文-简体';
        case 'en':
            lang.value = 'travel-yingguo';
            return 'English';
    }
}

/**
 * 切换多语言
 * @param e 
 */
function switchLang(e: any): void {
    if (e.key === i18n.global.locale) {
        return;
    }
    cache.setLocale(e.key);
    window.location.reload();
}

/**
 * 登录
 */
async function login(): Promise<void> {
    const originPwd: string = loginForm.password;
    try {
        spinning.value = true;
        loginForm.password = getMd5Suffix(originPwd);
        const response = await loginApi(loginForm);
        cache.setUserInfo(response);
        router.replace("/");
    } catch {
        loginForm.password = originPwd;
        await getVerificationCode();
    }
    finally {
        spinning.value = false;
    }
}
</script>

<style lang="less" scoped>
.login {
    margin: 0px;
    height: 100vh;
    background: url(../../assets/images/backGround.png) no-repeat center center;
    font-family: "Open Sans", sans-serif;
    background-size: cover;
    background-attachment: fixed;
    padding-top: 14%;

    .ant-form {
        dl {
            width: 440px;
            height: auto;
            overflow: hidden;
            margin: 0px auto;
            padding: 30px;
            box-shadow: 0 -15px 30px;
            border-radius: 5px;

            .ant-form-item label {
                color: white;
            }

            dt {
                font-size: 20px;
                font-weight: bold;
                text-align: center;
                color: #45bda6;
                text-shadow: 0 0 1px #0e947a;
                margin-top: 10px;
                margin-bottom: 20px;

                strong {
                    display: block;
                }
            }

            .lang {
                .anticon svg {
                    font-size: 18px;
                    margin-right: 5px;
                    margin-bottom: -2px;
                }
            }
        }
    }
}
</style>